/******************************************************************
 * Copyright (c) 2024 Bocloud Technologies Co., Ltd.
 * installer is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain n copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 ******************************************************************/

package v1beta1

import (
	confv1beta1 "gopkg.openfuyao.cn/bkecommon/cluster/api/v1beta1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (bc *BKECluster) GetNodeState(nodeIP string) confv1beta1.NodeStates {
	for _, nodeState := range bc.Status.NodesStatus {
		if nodeState.Node.IP == nodeIP {
			return nodeState.State
		}
	}
	return ""
}

func (bc *BKECluster) SetNodeStateWithMessage(nodeIP string, state confv1beta1.NodeStates, msg string) {
	nodesStatus := bc.Status.NodesStatus.DeepCopy()
	for i, nodeState := range nodesStatus {
		if nodeState.Node.IP == nodeIP {
			nodesStatus[i].State = state
			nodesStatus[i].Message = msg
			// 这个code只是标记这个节点的状态需要在更新时进行记录，无其他作用，会在被记录后由statusManager移除
			nodesStatus[i].StateCode |= NodeStateNeedRecord
			break
		}
	}
	bc.Status.NodesStatus = nodesStatus
}

func (bc *BKECluster) SetNodeState(nodeIP string, state confv1beta1.NodeStates) {
	nodesStatus := bc.Status.NodesStatus.DeepCopy()
	for i, nodeState := range nodesStatus {
		if nodeState.Node.IP == nodeIP {
			nodesStatus[i].State = state
			// 这个code只是标记这个节点的状态需要在更新时进行记录，无其他作用，会在被记录后由statusManager移除
			nodesStatus[i].StateCode |= NodeStateNeedRecord
			break
		}
	}
	bc.Status.NodesStatus = nodesStatus
}

func (bc *BKECluster) SetNodeStateMessage(nodeIP string, msg string) {
	nodesStatus := bc.Status.NodesStatus.DeepCopy()
	for i, nodeState := range nodesStatus {
		if nodeState.Node.IP == nodeIP {
			nodesStatus[i].Message = msg
			break
		}
	}
	bc.Status.NodesStatus = nodesStatus
}

func (bc *BKECluster) RemoveNodeState(nodeIP string) {
	nodesStatus := bc.Status.NodesStatus.DeepCopy()
	for i, nodeState := range nodesStatus {
		if nodeState.Node.IP == nodeIP {
			nodesStatus = append(nodesStatus[:i], nodesStatus[i+1:]...)
			break
		}
	}
	bc.Status.NodesStatus = nodesStatus
}

func (bc *BKECluster) MarkNodeStateFlag(nodeIP string, flag int) {
	nodesStatus := bc.Status.NodesStatus.DeepCopy()
	for i, nodeState := range nodesStatus {
		if nodeState.Node.IP == nodeIP {
			nodesStatus[i].StateCode |= flag
			break
		}
	}
	bc.Status.NodesStatus = nodesStatus
}

func (bc *BKECluster) UnmarkNodeState(nodeIP string, flag int) {
	nodesStatus := bc.Status.NodesStatus.DeepCopy()
	for i, nodeState := range nodesStatus {
		if nodeState.Node.IP == nodeIP {
			nodesStatus[i].StateCode &= ^flag
			break
		}
	}
	bc.Status.NodesStatus = nodesStatus
}

func (bc *BKECluster) GetNodeStateFlag(nodeIP string, flag int) bool {
	nodesStatus := bc.Status.NodesStatus.DeepCopy()
	for _, nodeState := range nodesStatus {
		if nodeState.Node.IP == nodeIP {
			return nodeState.StateCode&flag != 0
		}
	}
	return false

}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:shortName=bc
// +kubebuilder:printcolumn:name="PHASE",type="string",JSONPath=".status.phase"
// +kubebuilder:printcolumn:name="STATE",type="string",JSONPath=".status.clusterHealthState"
// +kubebuilder:printcolumn:name="CLUSTER STATUS",type="string",JSONPath=".status.clusterStatus"
// +kubebuilder:printcolumn:name="ENDPOINT",type="string",JSONPath=".spec.controlPlaneEndpoint.host"
// +kubebuilder:printcolumn:name="ENDPOINT PORT",type="string",JSONPath=".spec.controlPlaneEndpoint.port"
// +kubebuilder:printcolumn:name="VERSION",type="string",JSONPath=".status.kubernetesVersion"
// +kubebuilder:printcolumn:name="AGENT STATUS",type="string",JSONPath=".status.agentStatus.status"
// +kubebuilder:printcolumn:name="CONTAINER RUNTIME",type="string",JSONPath=".spec.clusterConfig.cluster.containerRuntime.cri",priority=1
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:metadata:labels={"cluster.x-k8s.io/provider=infrastructure-bke", "cluster.x-k8s.io/v1beta1=v1beta1"}
// BKECluster is the Schema for the bkeclusters API
type BKECluster struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   confv1beta1.BKEClusterSpec   `json:"spec,omitempty"`
	Status confv1beta1.BKEClusterStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
// BKEClusterList contains a list of BKECluster
type BKEClusterList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []BKECluster `json:"items"`
}

func init() {
	SchemeBuilder.Register(&BKECluster{}, &BKEClusterList{})
}
